package role

import (
	"context"
	"database/sql"
	"go-zero-project/common/excption"
	"go-zero-project/services/user/rpc/constans"
	"go-zero-project/services/user/rpc/internal/mapper"
	"go-zero-project/services/user/rpc/internal/mapper/bo"
	"go-zero-project/services/user/rpc/internal/mapper/entity"
	"go-zero-project/services/user/rpc/internal/svc"
	"go-zero-project/services/user/rpc/pb"
	"gorm.io/gorm"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
)

type SaveRoleLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewSaveRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveRoleLogic {
	return &SaveRoleLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *SaveRoleLogic) SaveRole(in *pb.SaveRoleReq) (*pb.SaveRoleResp, error) {
	// 1.check role name
	roleMapper := mapper.NewRoleMapper()
	roleBO := bo.SysRoleBO{RoleName: in.RoleName}
	selectCount, err := roleMapper.SelectCount(l.svcCtx.DBEngin, roleBO)
	if err != nil {
		return nil, err
	}
	if selectCount > 0 {
		return nil, excption.NewErrCode(constans.RoleNameIsExistError)
	}
	// 2.begin  Transaction
	returnRoleId, insertErr := l.txInsertRole(in, roleMapper)
	if insertErr != nil {
		return nil, insertErr
	}

	return &pb.SaveRoleResp{RoleId: returnRoleId}, nil
}

func (l *SaveRoleLogic) txInsertRole(in *pb.SaveRoleReq, roleMapper *mapper.RoleMapper) (int64, error) {
	roleEntity := entity.SysRoleEntity{DeptId: in.DeptId, RoleName: in.RoleName, Remark: in.RoleRemark,
		CreateTime: time.Now()}
	var returnRoleId int64
	insertErr := l.svcCtx.DBEngin.Transaction(func(tx *gorm.DB) error {
		// 1. 保存角色信息
		roleId, saveRoleErr := roleMapper.SaveRole(tx, roleEntity)
		if saveRoleErr != nil {
			return saveRoleErr
		}
		returnRoleId = roleId
		// 2.保存角色与菜单的关系
		if len(in.MenuIdArr) < 1 {
			return excption.NewErrCode(constans.RoleNoSelectMenu)
		}
		var roleMenuArr []entity.SysRoleMenuEntity
		for _, v := range in.MenuIdArr {
			roleMenu := entity.SysRoleMenuEntity{RoleId: sql.NullInt64{Int64: roleId, Valid: true},
				MenuId: sql.NullInt64{
					Int64: v, Valid: true}}
			roleMenuArr = append(roleMenuArr, roleMenu)
		}
		roleMenu, roleMenuInsertErr := mapper.NewRoleMenuMapper().BatchInsert(tx, roleMenuArr)
		if roleMenuInsertErr != nil {
			return roleMenuInsertErr
		}
		logx.Infof("保存角色与菜单的关系,id:%s", roleMenu)
		// 3.保存数据权限的关系
		if len(in.DeptIdArr) < 1 {
			return nil
		}
		var roleDeptArr []entity.SysRoleDeptEntity
		for _, v := range in.DeptIdArr {
			roleDept := entity.SysRoleDeptEntity{RoleId: roleId,
				DeptId: v}
			roleDeptArr = append(roleDeptArr, roleDept)
		}
		// 3.2 save to db
		roleDeptIdArr, insertRoleDeptIdErr := mapper.NewRoleDeptMapper().BatchInsert(l.svcCtx.DBEngin, roleDeptArr)
		if insertRoleDeptIdErr != nil {
			return insertRoleDeptIdErr
		}
		logx.Infof("保存数据权限的关系,id:%s", roleDeptIdArr)
		return nil
	})
	return returnRoleId, insertErr
}
